package com.ts.main.mini.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
import com.ts.main.mini.exception.CommonException;
import com.ts.main.mini.exception.R;
import com.ts.main.mini.mapper.FileMapper;
import com.ts.main.mini.properties.AlicloudProperties;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;


/**
 * @author lk
 * @date 2024/2/22 17:42
 */
@AllArgsConstructor
@Service
public class OssFileServiceImpl {

    private final AlicloudProperties alicloudProperties;

  /**
   * 阿里云 STS 服务获取临时访问凭证
   */
  public R ossSecurityToken() throws ClientException {
    String regionId = "cn-chengdu";
    String roleArn = "acs:ram::1233278087554006:role/ossrole";
    String roleSessionName = "kkSession";
    String policy = "{\n" +
      "    \"Version\": \"1\",\n" +
      "    \"Statement\": [\n" +
      "        {\n" +
      "            \"Effect\": \"Allow\",\n" +
      "            \"Action\": [\n" +
      "                \"oss:GetBucketAcl\",\n" +
      "                \"oss:GetBucketCors\",\n" +
      "                \"oss:GetBucketEncryption\",\n" +
      "                \"oss:GetBucketInfo\",\n" +
      "                \"oss:GetBucketInventory\",\n" +
      "                \"oss:GetBucketLifecycle\",\n" +
      "                \"oss:GetBucketLocation\",\n" +
      "                \"oss:GetBucketLogging\",\n" +
      "                \"oss:GetBucketPolicy\",\n" +
      "                \"oss:GetBucketReferer\",\n" +
      "                \"oss:GetBucketReplication\",\n" +
      "                \"oss:GetBucketReplicationLocation\",\n" +
      "                \"oss:GetBucketReplicationProgress\",\n" +
      "                \"oss:GetBucketRequestPayment\",\n" +
      "                \"oss:GetBucketTagging\",\n" +
      "                \"oss:GetBucketTransferAcceleration\",\n" +
      "                \"oss:GetBucketVersioning\",\n" +
      "                \"oss:GetBucketWebsite\",\n" +
      "                \"oss:GetBucketWorm\",\n" +
      "                \"oss:GetLiveChannel\",\n" +
      "                \"oss:GetLiveChannelHistory\",\n" +
      "                \"oss:GetLiveChannelStat\",\n" +
      "                \"oss:GetObject\",\n" +
      "                \"oss:GetObjectAcl\",\n" +
      "                \"oss:GetObjectTagging\",\n" +
      "                \"oss:GetObjectVersion\",\n" +
      "                \"oss:GetObjectVersionAcl\",\n" +
      "                \"oss:GetObjectVersionTagging\",\n" +
      "                \"oss:GetVodPlaylist\",\n" +
      "                \"oss:PutBucket\",\n" +
      "                \"oss:PutBucketAcl\",\n" +
      "                \"oss:PutBucketCors\",\n" +
      "                \"oss:PutBucketEncryption\",\n" +
      "                \"oss:PutBucketInventory\",\n" +
      "                \"oss:PutBucketLifecycle\",\n" +
      "                \"oss:PutBucketLogging\",\n" +
      "                \"oss:PutBucketPolicy\",\n" +
      "                \"oss:PutBucketReferer\",\n" +
      "                \"oss:PutBucketReplication\",\n" +
      "                \"oss:PutBucketRequestPayment\",\n" +
      "                \"oss:PutBucketTagging\",\n" +
      "                \"oss:PutBucketTransferAcceleration\",\n" +
      "                \"oss:PutBucketVersioning\",\n" +
      "                \"oss:PutBucketWebsite\",\n" +
      "                \"oss:PutLiveChannel\",\n" +
      "                \"oss:PutLiveChannelStatus\",\n" +
      "                \"oss:PutObject\",\n" +
      "                \"oss:PutObjectAcl\",\n" +
      "                \"oss:PutObjectTagging\",\n" +
      "                \"oss:PutObjectVersionAcl\",\n" +
      "                \"oss:PutObjectVersionTagging\"\n" +
      "            ],\n" +
      "            \"Resource\": [\n" +
      "                \"acs:oss:*:*:*\",\n" +
      "                \"acs:oss:*:*:*/*\"\n" +
      "            ]\n" +
      "        }\n" +
      "    ]\n" +
      "}";
    try {
      IClientProfile profile = DefaultProfile.getProfile(regionId, alicloudProperties.getAccessKey(), alicloudProperties.getSecretKey());
      DefaultAcsClient client = new DefaultAcsClient(profile);
      final AssumeRoleRequest request = new AssumeRoleRequest();
      request.setSysEndpoint("sts.cn-chengdu.aliyuncs.com");        // 地域
      request.setSysMethod(MethodType.POST);                        // post
      request.setRoleArn(roleArn);                                  // 角色ARN
      request.setRoleSessionName(roleSessionName);                  // 会话
      request.setPolicy(policy);                                    // 如policy为空，则用户将获得该角色下所有权限。
      request.setDurationSeconds(3600L);                            // 设置临时访问凭证的有效时间为3600秒。
      final AssumeRoleResponse response = client.getAcsResponse(request);
      return R.ok(response.getCredentials());
    } catch (ServerException e) {
      e.printStackTrace();
    }
    return null;
  }


  /**
   * 阿里云OSS的上传凭证
   *
   * @return
   */
  public R getOssFileToken() {
    //目录
    String dir = DateUtil.today();
    //ossClient实例
    OSS ossClient = new OSSClientBuilder().build(alicloudProperties.getOss().getEndpoint(), alicloudProperties.getAccessKey(), alicloudProperties.getSecretKey());
    try {
      //过期时间
      long expireTime = 3000;
      long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
      Date expiration = new Date(expireEndTime);
      PolicyConditions policyConditions = new PolicyConditions();
      policyConditions.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
      policyConditions.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
      //策略和签名
      String postPolicy = ossClient.generatePostPolicy(expiration, policyConditions);
      byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
      String encodedPolicy = BinaryUtil.toBase64String(binaryData);
      String postSignature = ossClient.calculatePostSignature(postPolicy);

      Map<String, String> respMap = new LinkedHashMap<String, String>();
      respMap.put("accessId", alicloudProperties.getAccessKey());
      respMap.put("policy", encodedPolicy);
      respMap.put("signature", postSignature);
      respMap.put("dir", dir);
      respMap.put("host", alicloudProperties.getOss().getHost());
      respMap.put("expire", String.valueOf(expireEndTime / 1000));
      return R.ok(respMap);
    } catch (Exception e) {
      throw new CommonException("获取上传令牌失败");
    }
  }

  /**
   * 上传文件
   */
  public String ossUploadFile(MultipartFile file) {
    OSS ossClient = new OSSClientBuilder().build(alicloudProperties.getOss().getEndpoint(), alicloudProperties.getAccessKey(), alicloudProperties.getSecretKey());
    final String filename = file.getOriginalFilename();
    Snowflake snowflake = IdUtil.getSnowflake(1, 1);
    String dir = "";
    if(!ObjectUtils.isEmpty(filename)){
      dir = DateUtil.today() + "/" + snowflake.nextIdStr() + filename.substring(filename.lastIndexOf("."));
    }
    try {
      PutObjectRequest putObjectRequest = new PutObjectRequest(alicloudProperties.getOss().getBucket(), dir, file.getInputStream());
      ossClient.putObject(putObjectRequest);
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (ossClient != null) {
        ossClient.shutdown();
      }
    }
    return dir;
  }


  /**
   * 批量上传
   */
  public List<String> ossUploadFileList(MultipartFile[] files) {
    final ArrayList<String> list = new ArrayList<>();
    for (MultipartFile multipartFile : files) {
      list.add(ossUploadFile(multipartFile));
    }
    return list;
  }

}
